home *** CD-ROM | disk | FTP | other *** search
- /*
- This is not a GPC demo program, but a utility to make the
- CRTSavePreviousScreen feature of the CRT unit work on Linux consoles
- for normal users (for root and other users with access to the
- virtual console memory devices, it works without this utility). It's
- currently only for Linux, but may easily be ported to other systems
- that have something similar to Linux' virtual console memory
- devices, and no "alternate screen" features or similar (where those
- are present (e.g. in xterms, but not on the Linux console), this
- utility isn't needed, either).
-
- Before installing it, please note that there is a little security
- issue: Direct access to the console's contents under Linux is done
- through the virtual console memory devices (/dev/vcsa*), rather than
- terminal operations, since kernel 1.1.92, so the system
- administrator can control access. This program is one way to grant
- limited access to them. It allows to save the screen contents and
- restore them later. As a security measure, to prevent terminal
- sniffing attacks, it refuses both saving and restoring while the
- invoking user has no read/write access to the corresponding
- terminal. This should be reasonably safe, but I can give no
- guarantee, so you might be careful about installing it on a
- multi-user system where security is a concern.
-
- That said, if you want to install it, you have to give it read/write
- permissions to the virtual console memory devices. E.g., create a
- group (say, vcs), set the group ownership of these devices and the
- executable of this program to that group, make the devices group
- readable and writable, and give the exectuable the setgid privilege.
-
- The following commands, executed as root, will do that:
-
- gcc -Wall -O3 -s -o crtscreen crtscreen.c
- groupadd vcs
- chgrp vcs /dev/vcsa* crtscreen
- chmod g=rw /dev/vcsa*
- chmod 2555 crtscreen
-
- It is NOT recommended to make this executable setuid root because
- that would increase the effects of any possible bugs.
-
- Copyright (C) 1999-2001 Frank Heckenbach <frank@g-n-u.de>
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation, version 2.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
- */
-
- #ifndef linux
- #error This program was only written for Linux.
- #endif
-
- #include <unistd.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <errno.h>
- #include <fcntl.h>
- #include <sys/types.h>
- #include <sys/stat.h>
-
- #define DEV_TTY "/dev/tty"
- #define DEV_VCSA "/dev/vcsa"
-
- static int VcsaFile, BufSize = 0x1000, Count = 0;
- static char *Buffer = 0, *tty;
-
- static int crt_save_restore_screen_internal (int Restore)
- {
- ssize_t r, c = 0;
- /* Check if access to the terminal is currently permitted, using the
- real user ID, in order to prevent terminal sniffing attacks. */
- if (access (tty, R_OK | W_OK))
- return 0;
- lseek (VcsaFile, 0, SEEK_SET);
- if (!Restore)
- do
- if ((!Buffer || c >= BufSize) && (!(Buffer = realloc (Buffer, BufSize *= 2))))
- return 0;
- else if ((r = read (VcsaFile, Buffer + c, BufSize - c)) >= 0)
- Count = c += r;
- else if (errno != EINTR)
- return 0;
- while (r);
- else if (!Count)
- return 0;
- else
- do
- if ((r = write (VcsaFile, Buffer + c, Count - c)) >= 0)
- c += r;
- else if (errno != EINTR)
- return 0;
- while (r && c < Count);
- return 1;
- }
-
- int main ()
- {
- char Mode, *t, Vcsa [100];
- if (!getenv ("DISPLAY") && isatty (2) && (tty = ttyname (2))
- && strlen (tty) <= sizeof (Vcsa) - strlen (DEV_VCSA) - 1
- && !strncmp (tty, DEV_TTY, strlen (DEV_TTY))
- && *(t = tty + strlen (DEV_TTY)) && !access (tty, R_OK | W_OK))
- {
- sprintf (Vcsa, DEV_VCSA "%s", t);
- while (*t >= '0' && *t <= '9') t++;
- if (!*t && (VcsaFile = open (Vcsa, O_RDWR)) >= 0)
- while (read (0, &Mode, 1) > 0)
- if (Mode == 'S' || Mode == 'R')
- {
- if (!crt_save_restore_screen_internal (Mode == 'R'))
- write (1, "E", 1);
- else if (write (1, "O", 1) < 0 && errno != EINTR)
- break;
- }
- }
- write (1, "F", 1);
- return 1;
- }
-